/*
 * ses_dcf77.c
 *
 *  Created on: Jun 24, 2011
 *      Author: Andre
 */

#include "ses_common.h"
#include "ses_dcf77.h"
#include "ses_led.h"
#include "ses_scheduler.h"

#include <string.h>

/******************Makros*********************************/

/**
 * Get the state of the DCF77 Data pin
 */
#define DCF77_PINSTATE (PIN(DCF77_PORT) & (1<<DCF77_PIN))

#define CHECK_TIMEOUT 10 //Check Pin every 50ms

#define SYNC_LOWCOUNT 150     //150 Lowcounts (1,5 Seconds) for syncronisation

#define ZERO_LOWER_HIGHCOUNT 5 //5 Highcount (0,05) for lower bound of a "0"
#define ZERO_UPPER_HIGHCOUNT 15 //15 Highcount (0,15) for upper bound of a "0"

#define ONE_LOWER_HIGHCOUNT 15 //15 Highcount (0,15) for lower bound of a "1"
#define ONE_UPPER_HIGHCOUNT 25 //25 Highcount (0,25) for upper bound of a "1"

/******************Interval Variables*********************/
uint8_t error;     //Error flag
uint8_t bitpos;    //Current Bitposition
uint8_t timedata[60]; //Raw time data
uint8_t offtime;   //Lowcount
uint8_t ontime;    //Highcount


void dcf77_PinToggle(){
	if(DCF77_PINSTATE){
		led_greenOn();
	} else {
		led_greenOff();
	}
}

void check_and_update_time(){
	type_timeRTC time;

	//Bits and values taken from http://de.wikipedia.org/wiki/DCF77#Zeitinformation
	time.minute = 0;
	time.minute += timedata[21] * 1;
	time.minute += timedata[22] * 2;
	time.minute += timedata[23] * 4;
	time.minute += timedata[24] * 8;
	time.minute += timedata[25] * 10;
	time.minute += timedata[26] * 20;
	time.minute += timedata[27] * 40;

	time.hour = 0;
	time.hour += timedata[29] * 1;
	time.hour += timedata[30] * 2;
	time.hour += timedata[31] * 4;
	time.hour += timedata[32] * 8;
	time.hour += timedata[33] * 10;
	time.hour += timedata[34] * 20;

	time.second = 0;
	time.milli = 0;

	display_clear();
	displayPrint_setCursor(0, 0);
	printf("Time: %02d:%02d", time.hour, time.minute);

	/* Set Time in the timer */
	//scheduler_setTimeRTC(&time);
}

static void dcf77_timerTask(){
	led_yellowToggle();

	if(error){
		led_redOn();
	} else {
		led_redOff();
	}

	//If Pinstate is HIGH ...
	if(DCF77_PINSTATE){
		if(offtime != 0){//First time High

			if(offtime > SYNC_LOWCOUNT){//Sync signal
				if(error == 0 && bitpos == 59){
					check_and_update_time();
					return;
				}

				display_clear();

				displayPrint_setCursor(0, 0);
				printf("(%d)",bitpos);

				/* Reset everything */
				error = 0;
				bitpos = 0;
				memset(timedata, 0, 60);
				ontime = 0;
			}

			//Reset offtime

		}

		offtime = 0;
		ontime++;
	} else { //... else if Pinstate is LOW ...



		if(ontime > 0 && error == 0){//... and was on ...

			//Check onetime for data
			if(ontime > ZERO_LOWER_HIGHCOUNT && ontime < ZERO_UPPER_HIGHCOUNT){
				printf("0");
				bitpos++;

			} else if(ontime > ONE_LOWER_HIGHCOUNT && ontime < ONE_UPPER_HIGHCOUNT){
				timedata[bitpos] = 1;
				printf("1");
				bitpos++;

			} else {
				error = 1;
			}

		}

		ontime = 0;
		offtime++;
	}

	/* Restart Timer */
	scheduler_add(dcf77_timerTask, CHECK_TIMEOUT);
}

void dcf77_init(){
	//Set Everything to zero
	error = 1; //In the beginning we search for sync
	bitpos = 0;
	memset(timedata, 0, 60);
	offtime = 0;
	ontime = 0;

	//Start dcf77 timer task
	scheduler_add(dcf77_timerTask, CHECK_TIMEOUT);
}
